﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JeuDeDames;

namespace JeuDeDames
{
    public class Humain : Joueur
    {
        public Humain(int color, string nom)
        {
            // TODO: Complete member initialization
            this.couleur = color;
            this.nom = nom;
            this.lesPieces = new List<Piece>();
            if (color == BLANC)
                this.monTour = true;
            else if (color == NOIR)
                this.monTour = false;
        }

        public Humain(int color) : this(color, "")
        {
            //creerHumain();
        }

        public void creerHumain()
        {
            //string saisieNom;
            if (couleur == NOIR)
            {
                Console.WriteLine("Veuillez entrer le nom du joueur blanc : ");
                nom = Console.ReadLine();
                Console.WriteLine("Joueur blanc : " + nom+"\n");
                Joueur blanc = new Humain(BLANC, nom);
            }
            else
            {
                Console.WriteLine("Veuillez entrer le nom du joueur noir : ");
                nom = Console.ReadLine();
                Console.WriteLine("Joueur noir : " + nom+"\n");
                Joueur noir = new Humain(NOIR, nom);
            }
            //nom = saisieNom;
        } // creerHumain()

        public void jouerIA(Coup coup, Damier damier)
        {
                bool aJouer = false;

                while (!aJouer)
                {
                    if ((Damier.damier[coup.origine.position] is CaseNoire) && ((Damier.damier[coup.origine.position] as CaseNoire).piece != null) && ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 1)
                    {
                        ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).seDeplacer(coup);
                        Damier.historiqueCoups.Add(coup);
                    }
                    else if (((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 2)
                    {
                        ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).mange(coup);
                        Damier.historiqueCoups.Add(coup);
                        this.coupsPossibles = calculCoupsPossibleQuiMangentApres(coup, damier);
                        if (coupsPossibles.Count() != 0)
                        {
                            jouer(coupsPossibles[0], damier);
                        }
                    }
                    aJouer = true;
                    Damier.nbTour++;
                }
        }

        public override void jouer(Coup coup, Damier damier)
        {
            if (coupsPossibles.Contains(coup))
            {
            bool aJouer = false;

            while (!aJouer)
            {
                /*Si c'est une case noire ET */
                if ((Damier.damier[coup.origine.position] is CaseNoire) && ((Damier.damier[coup.origine.position] as CaseNoire).piece != null ) && ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 1)
                {
                    ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).seDeplacer(coup);
                    Damier.historiqueCoups.Add(coup);
                }
                else if (((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).deplacementOuMangeage(coup.origine, coup.destination) == 2)
                {
                    ((Damier.damier[coup.origine.position] as CaseNoire).piece as Pion).mange(coup);
                    Damier.historiqueCoups.Add(coup);
                    this.coupsPossibles = calculCoupsPossibleQuiMangentApres(coup, damier);
                    if (coupsPossibles.Count() != 0)
                    {
                        Console.Clear();
                        damier.afficheDamier();
                        this.afficheCoupsPossibles();
                        coup = this.coupAJouer();
                        jouer(coup, damier);
                    }
                }
                aJouer = true;
                Damier.nbTour++;
            }
        }
            else
            {
                Console.WriteLine("Il vous est impossible de jouer ce coup. Veuillez choisir un coup valide");
                coupAJouer();
            }
        }

        /**
         * coupAjouer() demande au Joueur qu'elle coup veut-il faire.
         * @Regle : si une pièce est touchée, elle doit-être déplacée
         * => Si la pièce sélectionnée est "valide", elle devrat obligatoirement l'à jouer
         * @return : le coup à jouer
         * */
        /*
        public Coup coupAJouer()
        {
            int indiceCaseChoisi1 = 0;
            int indiceCaseChoisi2 = 0;
            bool test1;
            Coup coup = null;
            do
            {
                test1 = false;

                do
                {
                    Console.Write("Entrez la case de la pièce à déplacer : ");
                    string caseChoisi = Console.ReadLine();
                    indiceCaseChoisi1 = this.indiceTransformeur(caseChoisi);
                    if(!(Damier.damier[indiceCaseChoisi1] is CaseNoire))
                        indiceCaseChoisi1=-1;
                } while (indiceCaseChoisi1 == -1);

                do
                {
                    Console.Write("Entrez la case où mettre votre " + (Damier.damier[indiceCaseChoisi1] as CaseNoire).piece + ": ");
                    string caseChoisi2 = Console.ReadLine();
                    indiceCaseChoisi2 = this.indiceTransformeur(caseChoisi2);
                    if (!(Damier.damier[indiceCaseChoisi2] is CaseNoire))
                        indiceCaseChoisi2 = -1;
                } while (indiceCaseChoisi2 == -1);

                if ((Damier.damier[indiceCaseChoisi1] is CaseNoire) && (Damier.damier[indiceCaseChoisi2] is CaseNoire))
                {
                    if ((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece.deplacementOuMangeage(
                        (Damier.damier[indiceCaseChoisi1] as CaseNoire), (Damier.damier[indiceCaseChoisi2] as CaseNoire)) == 1)
                    {
                        CaseNoire orig = (Damier.damier[indiceCaseChoisi1] as CaseNoire);
                        CaseNoire dest = (Damier.damier[indiceCaseChoisi2] as CaseNoire);
                        coup = new Coup(this, orig, dest);
                    }
                    else if ((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece.deplacementOuMangeage(
                        (Damier.damier[indiceCaseChoisi1] as CaseNoire), (Damier.damier[indiceCaseChoisi2] as CaseNoire)) == 2)
                    {
                        CaseNoire orig = (Damier.damier[indiceCaseChoisi1] as CaseNoire);
                        CaseNoire dest = (Damier.damier[indiceCaseChoisi2] as CaseNoire);
                        Piece pMange = (Damier.damier[((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece as Pion).caseAManger(Damier.damier[indiceCaseChoisi2] as CaseNoire)] as CaseNoire).piece;
                        coup = new Coup(this, orig, dest, pMange);
                    }
                    foreach (Coup unCoup in coupsPossibles)
                    {
                        if (coup.Equals(unCoup))
                        {
                            coup = unCoup;
                            test1 = true;
                            return coup;
                        }
                    }
                }
                
            }while(test1==false);
            return coup;

        }
        */

        public Coup coupAJouer()
        {
            int indiceCaseChoisi1 = 0;
            int indiceCaseChoisi2 = 0;
            bool test1 = false;
            bool test2 = false;
            bool test3 = false;
            Coup coup = null;
            do
            {
                /*On entre la case d'origine*/
                do
                {
                    Console.Write("Entrez la case de la pièce à déplacer : ");
                    string caseChoisi = Console.ReadLine();
                    indiceCaseChoisi1 = indiceTransformeur(caseChoisi);
                    if (indiceCaseChoisi1 > 0 && indiceCaseChoisi1 < 144)
                    {
                        /*Si la case est noire ET la case contient une piece ET de la même couleur*/
                        if ((Damier.damier[indiceCaseChoisi1] is CaseNoire) && (!(Damier.damier[indiceCaseChoisi1] as CaseNoire).estVide()) && (Damier.damier[indiceCaseChoisi1] as CaseNoire).piece.couleur == this.couleur)
                            test1 = true;
                    }
                } while (test1 == false);

                /*On entre la case destination*/
                do
                {
                    Console.Write("Entrez la case où mettre votre " + (Damier.damier[indiceCaseChoisi1] as CaseNoire).piece + ": ");
                    string caseChoisi2 = Console.ReadLine();
                    indiceCaseChoisi2 = indiceTransformeur(caseChoisi2);
                    if (indiceCaseChoisi2 > 0 && indiceCaseChoisi2 < 144)
                    {
                        /*Si la case est noire ET la case ne contient pas de piece*/
                        if ((Damier.damier[indiceCaseChoisi2] is CaseNoire) && ((Damier.damier[indiceCaseChoisi2] as CaseNoire).estVide()))
                            test2 = true;
                    }
                } while (test2 == false);

                if ((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece.deplacementOuMangeage(
                            (Damier.damier[indiceCaseChoisi1] as CaseNoire), (Damier.damier[indiceCaseChoisi2] as CaseNoire)) == 1)
                {
                    CaseNoire orig = (Damier.damier[indiceCaseChoisi1] as CaseNoire);
                    CaseNoire dest = (Damier.damier[indiceCaseChoisi2] as CaseNoire);
                    coup = new Coup(this, orig, dest);
                    test3 = true;
                }
                else if ((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece.deplacementOuMangeage(
                    (Damier.damier[indiceCaseChoisi1] as CaseNoire), (Damier.damier[indiceCaseChoisi2] as CaseNoire)) == 2)
                {
                    CaseNoire orig = (Damier.damier[indiceCaseChoisi1] as CaseNoire);
                    CaseNoire dest = (Damier.damier[indiceCaseChoisi2] as CaseNoire);
                    Piece pMange = (Damier.damier[((Damier.damier[indiceCaseChoisi1] as CaseNoire).piece as Pion).caseAManger(Damier.damier[indiceCaseChoisi2] as CaseNoire)] as CaseNoire).piece;
                    coup = new Coup(this, orig, dest, pMange);
                    test3 = true;
                }
                else
                    test3 = false;
            }while(test3 == false);
            foreach (Coup unCoup in coupsPossibles)
            {
                if (coup.Equals(unCoup))
                {
                    coup = unCoup;
                    test1 = true;
                    return coup;
                }
            }
            return coup;
        }


        // transforme le code entré par la joueur en indice du tableau de case du damier
        public static int indiceTransformeur(string caseChoisie)
        {
            if (!(caseChoisie.Length > 3))
            {
            int resultat = 0;
            try
            {
                if (caseChoisie.Substring(0, 1) == "A" || caseChoisie.Substring(0, 1) == "a")
                {
                    resultat += 12;
                }
                else if (caseChoisie.Substring(0, 1) == "B" || caseChoisie.Substring(0, 1) == "b")
                {
                    resultat += 13;
                }
                else if (caseChoisie.Substring(0, 1) == "C" || caseChoisie.Substring(0, 1) == "c")
                {
                    resultat += 14;
                }
                else if (caseChoisie.Substring(0, 1) == "D" || caseChoisie.Substring(0, 1) == "d")
                {
                    resultat += 15;
                }
                else if (caseChoisie.Substring(0, 1) == "E" || caseChoisie.Substring(0, 1) == "e")
                {
                    resultat += 16;
                }
                else if (caseChoisie.Substring(0, 1) == "F" || caseChoisie.Substring(0, 1) == "f")
                {
                    resultat += 17;
                }
                else if (caseChoisie.Substring(0, 1) == "G" || caseChoisie.Substring(0, 1) == "g")
                {
                    resultat += 18;
                }
                else if (caseChoisie.Substring(0, 1) == "H" || caseChoisie.Substring(0, 1) == "h")
                {
                    resultat += 19;
                }
                else if (caseChoisie.Substring(0, 1) == "I" || caseChoisie.Substring(0, 1) == "i")
                {
                    resultat += 20;
                }
                else if (caseChoisie.Substring(0, 1) == "J" || caseChoisie.Substring(0, 1) == "j")
                {
                    resultat += 21;
                }
                else
                {
                    throw new System.NullReferenceException("Erreur, cette case n'existe pas.#1");
                }
            }
            catch (NullReferenceException)
            {
                Console.WriteLine("La case n'existe pas.#2");
                return resultat = -1;
            }
            catch (ArgumentOutOfRangeException)
            {
                Console.WriteLine("Il vous faut sélectionner une case.#7");
                return resultat = -1;
            }
            catch (FormatException)
            {
                Console.WriteLine("Mauvais format de case.#9");
                return resultat = -1;
            }
            
            int numero;
            try
            {
                numero = int.Parse(caseChoisie.Substring(1, 2));
                resultat += 12 * (numero - 1) + 1;
            }
            catch (ArgumentOutOfRangeException)
            {
                try
                {
                    numero = int.Parse(caseChoisie.Substring(1, 1));
                    resultat += 12 * (numero - 1) + 1;
                }
                catch (ArgumentOutOfRangeException)
                {
                    Console.WriteLine("Valeur de la case incomplète.#3");
                    return resultat = -1;
                }

                catch (NullReferenceException)
                {
                    Console.WriteLine("La case entrée n'existe pas.#5");
                    return resultat = -1;
                }
                    catch (IndexOutOfRangeException)
                    {
                        Console.WriteLine("La case entrée n'existe pas.#4");
                        return resultat = -1;
            }
                    catch (FormatException)
                    {
                        Console.WriteLine("Le format de la case n'existe pas");
                        return resultat = -1;
                    }
                }
            catch (NullReferenceException)
            {
                Console.WriteLine("La case entrée n'existe pas.#6");
                return resultat = -1;
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("La case entrée n'existe pas.#4");
                return resultat = -1;
            }
            catch (FormatException)
            {
                Console.WriteLine("Le format de la case n'existe pas");
                return resultat = -1;
            }
            return resultat;
            }

            Console.WriteLine("Le format de la case n'existe pas");
            return -1;
        }

        public override string ToString()
        {
            return base.ToString();
        }
    }
}
